package com.sudo.rpc.server.listener;

import com.sudo.rpc.api.common.Constant;
import com.sudo.rpc.api.model.RegistryServer;
import com.sudo.rpc.api.service.RmiSetServerService;
import com.sudo.rpc.api.utils.RegistryUtil;
import com.sudo.rpc.server.annotation.TaskComponent;
import com.sudo.rpc.server.config.FxwRpcProperties;
import com.sudo.rpc.server.task.registry.BaseTaskRegistry;
import com.sudo.rpc.server.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.util.Map;

/**
 * 启动后加载指定bean
 */
@Slf4j
public class ContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
    @Resource
    private FxwRpcProperties fxwRpcProperties;
    @Resource
    private RmiSetServerService rmiSetServerService;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 根容器为Spring容器
        ApplicationContext applicationContext = event.getApplicationContext();
        SpringContextUtil.setApplicationContext(applicationContext);
        if (applicationContext.getParent() == null) {
            Map<String, Object> taskComponentMap = applicationContext.getBeansWithAnnotation(TaskComponent.class);

            taskComponentMap.forEach((k,v) -> {
                Class<?> targetClass = AopUtils.getTargetClass(v);
                BaseTaskRegistry.setModuleClassMap(k, targetClass);
            });
            // 加载硬件资源包
            loadSigarResources();

            // 服务启动并向远程注册
            startAndRegistry();
        }
    }

    private void startAndRegistry() {

        Integer localRegistryPort = fxwRpcProperties.getLocalRegistryPort();

        RegistryServer registryServer = BaseTaskRegistry.getRegistryServer();
        registryServer.setPort(localRegistryPort);

        // 1.启动服务
        RegistryUtil.startRegistry(localRegistryPort);
        Registry registry = RegistryUtil.getRegistry(localRegistryPort);

        // 1.2注册服务
        try {
            registry.rebind(Constant.registryCenter,rmiSetServerService);
        } catch (RemoteException e) {
            log.error("服务注册失败：", e);
        }

        try{
            // 2.连接管理端
            rmiSetServerService.pushServer(registryServer);
        }catch (Exception e){
            log.error("连接管理端失败，请手动注册：", e);
        }
    }

    private void loadSigarResources() {
        String sigar = "libsigar-amd64-linux.so";
        boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
        if (isWin){
            sigar = "sigar-amd64-winnt.dll";
        }
        String resourceAbsolutePath = getResourceAbsolutePath(sigar);
        System.load(resourceAbsolutePath);
    }

    public String getResourceAbsolutePath(String name) {
        ClassLoader classLoader = this.getClass().getClassLoader();
        InputStream in = classLoader.getResourceAsStream(name);
        byte[] buffer = new byte[1024];
        int read = -1;
        File temp = null;
        FileOutputStream fos = null;
        try {
            temp = File.createTempFile(name,"");
            temp.deleteOnExit();
            fos = new FileOutputStream(temp);

            while((read = in.read(buffer)) != -1) {
                fos.write(buffer, 0, read);
            }
        } catch (IOException e) {
            throw new RuntimeException("加载资源包"+ name +"失败",e);
        }finally {
            try {
                fos.close();
                in.close();
            } catch (IOException e) {
                throw new RuntimeException("关闭流失败",e);
            }
        }
        return temp.getAbsolutePath();
    }
}
